package com.hanxiaozhang.tree.binarytreerecursion;

import com.hanxiaozhang.tree.BinaryTreeUtil;
import com.hanxiaozhang.tree.Node;

/**
 * 〈一句话功能简述〉<br>
 * 〈给定一棵二叉树的头节点head，返回这颗二叉树是不是平衡二叉树〉
 *
 * @author hanxinghua
 * @create 2021/10/28
 * @since 1.0.0
 */
public class IsBalanced {

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isBalanced1(head) != isBalanced2(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }


    /**
     * 是否平衡方法1
     *
     * @param head
     * @return
     */
    public static boolean isBalanced1(Node head) {
        boolean[] ans = new boolean[1];
        ans[0] = true;
        process1(head, ans);
        return ans[0];
    }

    /**
     * 递归1
     *
     * @param head
     * @param ans
     * @return 树的高度
     */
    public static int process1(Node head, boolean[] ans) {
        // !ans[0] -> 不是平衡树  head == null -> 树是空树
        if (!ans[0] || head == null) {
            return -1;
        }
        int leftHeight = process1(head.left, ans);
        int rightHeight = process1(head.right, ans);
        // 左右子树高度差超过 1
        if (Math.abs(leftHeight - rightHeight) > 1) {
            ans[0] = false;
        }
        // 返回树的高度
        return Math.max(leftHeight, rightHeight) + 1;
    }

    /**
     * 是否平衡方法2
     *
     * @param head
     * @return
     */
    public static boolean isBalanced2(Node head) {
        return process2(head).isBalaced;
    }

    /**
     * 递归2
     *
     * @param head
     * @return
     */
    public static Info process2(Node head) {
        // base case
        if (head == null) {
            return new Info(true, 0);
        }
        Info leftInfo = process2(head.left);
        Info rightInfo = process2(head.right);
        // 当前树的高度 = 左右节点最大高度 + 父节点高度
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        // 判断平衡条件
        boolean isBalanced = true;
        if (!leftInfo.isBalaced || !rightInfo.isBalaced || Math.abs(leftInfo.height - rightInfo.height) > 1) {
            isBalanced = false;
        }
        return new Info(isBalanced, height);
    }


    /**
     * 生成平衡树
     *
     * @param maxLevel
     * @param maxValue
     * @return
     */
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return BinaryTreeUtil.generate(1, maxLevel, maxValue);
    }




    /**
     * 实体
     */
    private static class Info {
        /**
         * 是否平衡
         */
        public boolean isBalaced;
        /**
         * 高度
         */
        public int height;

        public Info(boolean b, int h) {
            isBalaced = b;
            height = h;
        }
    }


}
